package com.github.byakkili.bim.autoconfigure;

import cn.hutool.core.collection.CollUtil;
import com.github.byakkili.bim.core.BimConfiguration;
import com.github.byakkili.bim.core.BimNettyServer;
import com.github.byakkili.bim.core.cluster.ClusterManager;
import com.github.byakkili.bim.core.handler.command.CommandProcessor;
import com.github.byakkili.bim.core.interceptor.CommandInterceptor;
import com.github.byakkili.bim.core.listener.SessionListener;
import com.github.byakkili.bim.core.protocol.Protocol;
import com.github.byakkili.bim.core.threadpool.ThreadPool;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.List;

/**
 * @author Guannian Li
 */
@Configuration
@RequiredArgsConstructor
@EnableConfigurationProperties(BimProperties.class)
public class BimAutoConfiguration {

    private final BimProperties properties;
    private final List<Protocol> protocols;
    private final List<CommandProcessor> commandProcessors;

    @Autowired(required = false)
    private ThreadPool threadPool;
    @Autowired(required = false)
    private ClusterManager clusterManager;
    @Autowired(required = false)
    private List<SessionListener> sessionListeners;
    @Autowired(required = false)
    private List<CommandInterceptor> commandInterceptors;

    @Bean
    public BimConfiguration configuration() {
        BimConfiguration config = new BimConfiguration();
        config.setBindIp(properties.getBindIp());
        config.setBindPort(properties.getBindPort());
        config.setIdleTimeout(properties.getIdleTimeout());
        config.setKeepAlive(properties.isKeepAlive());
        config.setIoThread(properties.getIoThread());

        config.setThreadPool(threadPool);
        config.setClusterManager(clusterManager);

        protocols.forEach(config.getProtocols()::add);
        commandProcessors.forEach(config::addCommandProcessor);

        CollUtil.emptyIfNull(sessionListeners).forEach(config.getSessionListeners()::add);
        CollUtil.emptyIfNull(commandInterceptors).forEach(config.getCommandInterceptors()::add);

        return config;
    }

    @Bean
    public BimNettyServer bimNettyServer() {
        return new BimNettyServer(configuration());
    }

    @Bean
    public BimServerStartStopLifecycle bimServerStartStopLifecycle() {
        return new BimServerStartStopLifecycle(bimNettyServer());
    }
}
